#include "syscore.h"
#include "apis.h"
#include "common.h"
#include <string>
#include <errno.h>
#include "logger.h"

static MODREG modLogServerInfo = {MODULE_LOG_SERVER, true, false, 5000, (char*)"logServer"};

class logServerThreadData
{
public:
    std::string comName_;
    std::string path_;
    int mode_;
};

void handleLogServerTick()
{
    U32 rc = PARA_VALUE_SYSMONITOR_MODULE_OK;
    CM_SendMsg_1Para(MODULE_SYSMONITOR, MODULE_LOG_SERVER, MSG_TYPE_COMMAND, CMD_EVENT, CMD_CODE_SYSMONITOR_HEARTBEAT, 0,
        PARA_TYPE_SYSMONITOR_MODULE_STATE, sizeof(U32), (U8*)&rc);  
}

static void* logServerMainTask(void *arg)
{
    if( RC_OK != MOD_register(&modLogServerInfo) )
    {
        dbgprintf(DEBUG_ERROR, stderr, "%s: Can't register module with logServer\n", __func__);
        return false;
    }
    
    logServerThreadData* dataPtr = static_cast<logServerThreadData*>(arg);
    if( dataPtr==NULL )
    {
        dbgprintf(DEBUG_ERROR, stderr, "%s: NULL pointer", __func__);
        return NULL;
    }
    dbgprintf(DEBUG_ALWAYS, stderr, "logServerMainTask id is %lu \n", pthread_self()); 
    pthread_setname_np(pthread_self(), "logServer");

    Logger::LOG_MODE mode = Logger::LOG_REAL_TIME;
    if( dataPtr->mode_==1 )
    {
        mode = Logger::LOG_MESSAGE;
    }
    if( !LoggerPtr->initialize(dataPtr->comName_, dataPtr->path_, mode, MSG_send) )
    {
        dbgprintf(DEBUG_ERROR, stderr, "[0x%x] Fail to initizlize logger\n", 0x010C);
    }

    if( dataPtr!=NULL )
    {
        delete dataPtr;
        dataPtr = NULL;
    }

    LoggerPtr->SetLogLevel(LOG_NOTICE);
    
    uint8_t recvMsgBuf[65535] = {0};
    MSGHEADER *msgHeader = (MSGHEADER *)recvMsgBuf;
    void* payload = (void*)(recvMsgBuf + sizeof(MSGHEADER));

    while( 1 )
    {
        if( RC_OK == MSG_read(MODULE_LOG_SERVER, msgHeader, payload) )
        {
            switch(msgHeader->msgType)
            {
                case MSG_TYPE_INTERNAL: 
                {
                    std::string logContent((char*)payload, msgHeader->msgLength-sizeof(MSGHEADER));
                    LoggerPtr->ServerLogToStream(logContent);
                    break;
                }
                case MSG_TYPE_TICK:
                {
                    handleLogServerTick();
                    break;
                }
                default:
                {
                    dbgprintf(DEBUG_INFO, stderr, "LogServer recvs invalid msg type: %d \n", msgHeader->msgType); 
                }
            }
        }
    }
    return NULL;
}

bool createLogServerTask(std::string comName, std::string path, int mode)
{    
    logServerThreadData* data = new logServerThreadData();
    if( data==NULL )
    {
        dbgprintf(DEBUG_ERROR, stderr, "%s: Fail to allocate buf", __func__);
        return false;
    }
    
    data->comName_ = comName;
    data->path_ = path;
    data->mode_ = mode;
    pthread_t       thread;
    if( pthread_create(&thread, NULL, logServerMainTask, data) )
    {
        dbgprintf(DEBUG_INFO, stdout, "pthread_create createLogServerTask thread failed: %s", strerror(errno));
        return false;
    }
    return true;
}

RESULT LogServer_init(const char* comName, const char* path, int mode)
{
    std::string comNameStr(comName, strlen(comName));
    std::string logPath(path, strlen(path));
    if( !createLogServerTask(comNameStr, logPath, mode) )
    {
        dbgprintf(DEBUG_ERROR, stderr, "%s: Fail to initialize LogServer\n", __func__);
        return RC_FAIL;
    }

    dbgprintf(DEBUG_INFO, stdout, "[0x%x]: LogServer_init is successful", MODULE_LOG_SERVER);
    return RC_OK;
}
